<?php

class TaskService extends BaseService {
   
	
	public function addTask($task) {
		try {
			$newTask = new Task;
			$newTask->setAttributes($task, false);
			$status = $newTask->save();
	
			return $status == true ? $newTask->task_id : $status;
		}
		catch(Exception $e) {
			Yii::log("add task error:" . $e->getMessage(), CLogger::LEVEL_ERROR);
			return false;
		}
	}

	public function editTask($task) {
		if(!isset($task['task_id'])) {
			return false;
		}
		
		try {
			$transaction = Task::model()->dbConnection->beginTransaction();
			$taskModel = Task::model()->findByPk($task['task_id']);
			
			$taskModel->setAttributes($task, false);
			$status = $taskModel->save();
			$transaction->commit();	
			return $status;
		}
		catch(Exception $e) {
			if($transaction != null) {
				$transaction->rollBack();
			}
			Yii::log("editTask error:" . $e->getMessage(), CLogger::LEVEL_ERROR);
			return false;
		}
	}
	
	public function editTaskAttributes($taskId, $attributes, $conditions = '', $params = array()) {
		try {
			return Task::model()->updateByPk($taskId, $attributes, $conditions, $params);
		}
		catch (Exception $e) {
			Yii::log("editTaskAttributes error:" . $e->getMessage(), CLogger::LEVEL_ERROR);
			return false;
		}
	}
	
	public function editAllTaskAttributes($attributes, $conditions = '', $params = array()) {
		try {
			return Task::model()->updateAll($attributes, $conditions, $params);
		}
		catch (Exception $e) {
			Yii::log("editAllTaskAttributes error:" . $e->getMessage(), CLogger::LEVEL_ERROR);
			return false;
		}
	}
	
	public function rerunTask($id) {
		try {		
			$db = Task::model()->dbConnection;
            $command = $db->createCommand('insert into task(job_id, date, state, task_type, workflow_name, frequency, priority, executor_id) select job_id, date, '
            . TaskState::Waiting .', task_type, workflow_name, frequency, priority, executor_id from task where task_id ='. $id);
			return $command->execute();
		}
		catch(Exception $e) {
			Yii::log("rerun task error:" . $e->getMessage(), CLogger::LEVEL_ERROR);
			return false;
		}
	}
	
	public function getTaskById($taskId) {
		$taskModel = Task::model()->with('job', 'command')->findByPk($taskId);
		 
		return $this->toArray($taskModel, array('job', 'command'));
	}

	public function getTasks($conditions, $with = null) {
		
		if(!($conditions instanceof CDbCriteria)) {
			$criteria = $this->toCriteria($conditions);
		}
		else {
			$criteria = $conditions;
		}

		if($with != null) {
			$tasks = Task::model()->with($with)->findAll($criteria);
			return $this->toArray($tasks, $with);
		}
		else {
			$tasks = Task::model()->findAll($criteria);
			return $this->toArray($tasks);
		}
	}
	
	public function getWaitingTasks() {
		$criteria =	new CDbCriteria(array(
			'condition'	=>	'state=:state',
			'params'	=>	array(
				':state'	=>	TaskState::Waiting,
			)
		));
		
		return $this->getTasks($criteria);
	}
	
	public function getReadyTasks($executorId) {
		try {		
			$db = Task::model()->dbConnection;
            $command = $db->createCommand('SELECT * From task WHERE state='. TaskState::Ready . ' and executor_id=' . $executorId .
            	' order by IF(frequency < 1440 and cmd_id is null, priority + 1, priority) desc, frequency asc, cmd_id is null desc, date asc');
			$readyTasks = $command->queryAll();
			return $readyTasks;
		}
		catch(Exception $e) {
			Yii::log("get ready task error:" . $e->getMessage(), CLogger::LEVEL_ERROR);
			return false;
		}
	}
	
	public function getFailedTasks($date, $taskType) {
		$beginDate = DateHelper::makeExactDate(
			DateHelper::normalizeDate(strtotime($date) - 1440*60, 1440));
			
		$sql = "SELECT pid, entity_id, date, state, type, freq, priority FROM tblTask WHERE date>='$beginDate' AND date<'$date' AND type=$taskType AND cmd_id IS NULL GROUP BY entity_id, date, state ORDER BY entity_id, date, state";
		$db = Task::model()->dbConnection;
		$tasks = $db->createCommand($sql)->queryAll();
		
		// choose the task only have failed status 
		// without 'running, waiting, ready, suceed' status
		$current = '';
		$failedTasks = array();		
		foreach ($tasks as $task) {
			$relyResource = MetaBaseService::getInstance()->getResourceByID($task['entity_id']);
			if(!isset($relyResource)) {
				continue;
			}
			
			$multiKey = "{$task['entity_id']}_{$task['date']}";
			if($current !== $multiKey) {
				$current = $multiKey;
				if($task['state'] == TaskState::Failed) {
					$failedTasks[] = $task;
				}
			}
		}
		return $failedTasks;
	}

	public function getTaskCount($conditions, $with = null) {
		$criteria = $this->toCriteria($conditions);

		if($with != null) {
			return Task::model()->with($with)->count($criteria);
		}
		else {
			return Task::model()->count($criteria);
		}
	}
	
	public function checkDuplication($entityId, $date, $type) {
		$count = $this->getTaskCount(
			array(
				'condition'		=>		array(
					array('job_id', '=', $entityId),
					array('date', '=', $date),
					array('task_type', '=', $type),
					array('state', 'in', array(TaskState::Waiting, TaskState::Ready, TaskState::Pending, TaskState::Running)),
				)
			)
		);
		return $count > 0;
	}
	
	public function checkState($taskId, $state) {
		$taskModel = Task::model()->findByPk($taskId);

		if($taskModel === null) {
			return false;
		}

		if(in_array($taskModel->state, $state)) {
			return $taskModel->state;
		}
		else {
			return false;
		}
	}
}

